package web

import (
	"fmt"
	"net"
	"net/http"
)

type HandleFunc func(ctx *Context)

// 确保HTTPServer结构体一定实现了Server
var _ Server = &HTTPServer{}

type Server interface {
	http.Handler
	Start(addr string) error
	// StartHttp() error

	// addRoute 需要增加路由注册的功能
	// method 请求方法
	// path 路由
	// handleFunc 业务逻辑
	addRoute(method string, path string, handleFunc HandleFunc)
	// 注册多个(没必要提供，用户可以自己根据addRoute实现)
	// addRoutes(method string, path string, handleFunc ...HandleFunc)
}

// type HTTPSServer struct {
// 	HTTPServer // 装饰HTTPServer
// }

type HTTPServerOption func(server *HTTPServer)

type HTTPServer struct {
	// addr string // 可以创建时传递，而不是通过start传，也是可以的
	// router
	router // 因为router实现了addRoute，所以也可以通过编译

	mdls []Middleware

	log func(msg string, args ...any)

	tplEngine TemplateEngine
}

// 缺乏扩展性
func NewHTTPServerV1(mdls ...Middleware) *HTTPServer {
	return &HTTPServer{
		router: newRouter(),
		mdls:   mdls,
	}
}

// 初始化server
func NewHTTPServer(opts ...HTTPServerOption) *HTTPServer {
	res := &HTTPServer{
		router: newRouter(),
		log: func(msg string, args ...any) {
			fmt.Printf(msg, args...)
		},
	}
	for _, opt := range opts {
		opt(res)
	}
	return res
}

func ServerWithMiddleware(mdls ...Middleware) HTTPServerOption {
	return func(server *HTTPServer) {
		server.mdls = mdls
	}
}

func ServerWithTemplateEngine(tplEngin TemplateEngine) HTTPServerOption {
	return func(server *HTTPServer) {
		server.tplEngine = tplEngin
	}
}

// http.Handler的接口
// 核心方法 处理请求的入口
func (h *HTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	// 框架代码
	ctx := &Context{
		Req:       req,
		Resp:      w,
		tplEngine: h.tplEngine,
	}
	// 最后一个handler是这个
	root := h.serve
	// 利用最后一个,从后往前回溯,组装链条
	// 后一个作为前一个的next 构造链条
	for i := len(h.mdls) - 1; i >= 0; i-- {
		root = h.mdls[i](root)
	}
	// 这里执行就是从前往后的

	// 最后把RespData和RespStatusCode刷新到响应
	var m Middleware = func(next HandleFunc) HandleFunc {
		return func(ctx *Context) {
			// 这里就设置了RespData和RespStatusCode
			next(ctx)
			h.flushResp(ctx)
		}
	}

	root = m(root)

	root(ctx)
	// 接下来就是查找路由并执行命中的业务逻辑
	//h.serve(ctx)
}

func (h *HTTPServer) flushResp(ctx *Context) {
	if ctx.RespStatusCode != 0 {
		ctx.Resp.WriteHeader(ctx.RespStatusCode)
	}
	n, err := ctx.Resp.Write(ctx.RespData)
	if err != nil || n != len(ctx.RespData) {
		//log.Fatalln("写入响应失败")
		h.log("写入响应失败 %v\n", err)
	}
}

func (h *HTTPServer) serve(ctx *Context) {
	info, ok := h.findRoute(ctx.Req.Method, ctx.Req.URL.Path)
	if !ok || info.n.handler == nil {
		// 路由没命中，404
		//ctx.Resp.WriteHeader(404)
		//ctx.Resp.Write([]byte("NOT FOUND"))
		ctx.RespData = []byte("NOT FOUND")
		ctx.RespStatusCode = 404
		return
	}
	ctx.PathParams = info.pathParams
	ctx.MatchedRoute = info.n.route
	info.n.handler(ctx)
}

func (h *HTTPServer) Start(addr string) error {
	// 也可以自己创建server
	// http.Server{}
	l, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}

	// 在这里可以让用户注册 after、start 等回调(生命周期)
	// 比如往 admin 注册这个实例
	// 或者执行一些业务所需的前置条件

	return http.Serve(l, h)
}

// func (h *HTTPServer) addRoute(method string, path string, handleFunc HandleFunc) {
// 	// 注册到路由树
// 	panic("implement me")
// }

// 接口定义的东西尽量简洁
// 提供多种实现
func (h *HTTPServer) Get(path string, handleFunc HandleFunc) {
	h.addRoute(http.MethodGet, path, handleFunc)
}

func (h *HTTPServer) Post(path string, handleFunc HandleFunc) {
	h.addRoute(http.MethodPost, path, handleFunc)
}

func (h *HTTPServer) Put(path string, handleFunc HandleFunc) {
	h.addRoute(http.MethodPut, path, handleFunc)
}

func (h *HTTPServer) Patch(path string, handleFunc HandleFunc) {
	h.addRoute(http.MethodPatch, path, handleFunc)
}

func (h *HTTPServer) Delete(path string, handleFunc HandleFunc) {
	h.addRoute(http.MethodDelete, path, handleFunc)
}

// func (h *HTTPServer) addRoutes(method string, path string, handleFunc ...HandleFunc) {
// 	panic("implement me")
// }

func (h *HTTPServer) StartHttp(addr string) error {
	return http.ListenAndServe(addr, h)
}
